树莓派第一个驱动

您所在的位置:网站首页 linux helloworld驱动程序 树莓派第一个驱动

树莓派第一个驱动

2023-09-22 18:44| 来源: 网络整理| 查看: 265

驱动程序是硬件与操作系统之间的桥梁 驱动编写分为4个部分:第一步包含头文件第二步驱动模块的入口和出口第三步声明模块拥有开源许可证第四步功能实现helloworld 代码 驱动编译第一种方法第二种方法(把驱动编译进内核)第一步,在~/内核源码位置/drivers/char/目录下创建文件hello第二步,在hello文件夹创建helloworld.c第三步,在hello文件夹创建Makefile文件,并编写内容,如下第五步,返回hello文件的上一级即char文件夹,修改Makefile文件内容第六步,修改char文件夹的Kconfig文件第七步,返回到内核源码文件目录,修改menuconfig,第八步,通过.config检查是否添加成功(此步可以忽略)第九步,编译内核第十步,编译完内核后,会在~/build_new/linux/arch/arm64/boot下生成镜像第十一步,把sd卡挂载到虚拟机最后将sd卡插入树莓派。

驱动编写分为4个部分:

1头文件 2驱动模块的入口和出口 3声明信息 4.功能实现 b站链接: link

第一步包含头文件

#include 包含宏定义的头文件 #include 包含初始化加载模块的头文件

第二步驱动模块的入口和出口

module_init(); module_exit();

第三步声明模块拥有开源许可证

MODULE_LICENSE(“GPL”);

第四步功能实现

static int hello_init(void) { printk(“hello world \n”); return 0; }

static void hello_exit(void) { printk(“bye bye \n”); }

内核模块加载的时候打印hello world ,内核模块卸载的时候打印bye bye 注意:打印的时候不能用printf()函数,用printk()函数,内核里面没有printf()函数 利用printk打印信息的时候得有\r\n,不然不会立即显示,只有下次需要打印的时候才把上次的数据给显示出来

helloworld 代码 //第一步,包含头文件 #include //包含宏定义的头文件 #include //包含初始化加载模块的头文件 static int hello_init(void) { printk("hello world \n"); return 0; } static void hello_exit(void) { printk("bye bye \n"); } //第二步,驱动模块的入口和出口 module_init(hello_init); module_exit(hello_exit); //第三步,声明模块拥有开源许可证 MODULE_LICENSE("GPL"); //第四步,功能的实现 驱动编译

第一种方法:把驱动编译成模块,然后使用命令把驱动加载到内核里面

第二种方法:直接把驱动编译到内核

第一种方法

自行前往B站观看链接: link

在编译驱动的时候,按照该老师的方法报错,我采用的指令是

make ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- # aarch-linux-gnu-是我给交叉编译器重命的名 #arm64是指64位 #arm32是32位

加载驱动模块指令 insmod helloworld.ko 查看驱动是否加载上指令 lsmod 卸载驱动模块指令 rmmod helloworld 在加载过程中报错原因insmod、rmmod指令在sbin目录下,并不在bin目录下,可以将insmod与rmmod拷贝到bin目录,若没权限许可,加sudo 。 在执行该驱动的时候,未看见打印的信息,可以利用指令dmesg查看,清除内核log指令为dmesg -c。

第二种方法(把驱动编译进内核)

B站链接: link

第一步,在~/内核源码位置/drivers/char/目录下创建文件hello cd ~/build_new/linux/drivers/char #我的内核源码是存放在~/build_new/linux下的 mkdir hello 第二步,在hello文件夹创建helloworld.c //第一步,包含头文件 2 #include //包含宏定义的头文件 3 #include //包含初始化加载模块的头文件 4 5 static int hello_init(void) 6 { 7 printk("hello world \n"); 8 return 0; 9 } 10 11 static void hello_exit(void) 12 { 13 printk("bye bye \n"); 14 } 15 //第二步,驱动模块的入口和出口 16 module_init(hello_init); 17 module_exit(hello_exit); 18 19 20 //第三步,声明模块拥有开源许可证 21 MODULE_LICENSE("GPL"); 第三步,在hello文件夹创建Makefile文件,并编写内容,如下 touch Makefile vim Makefile obj-$(CONFIG_HELLO)+=helloworld.o

第四步,在hello文件夹创建Kconfig文件,并编写如下内容

touch Kconfig vim Kconfig config HELLO tristate "hello world" help hello hello 第五步,返回hello文件的上一级即char文件夹,修改Makefile文件内容 在第一行添加如下内容 obj-y += hello/ 第六步,修改char文件夹的Kconfig文件 在 menu "Character devices"下添加 source "drivers/char/hello/Kconfig"

在这里插入图片描述

第七步,返回到内核源码文件目录,修改menuconfig, cd ~/build_new/linux make ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- menuconfig #aarch64-linux-gnu-为我的交叉编译器名字

在这里插入图片描述 空格进行选择,*代表编译进内核,M代表编译为模块 修改后保存退出。

第八步,通过.config检查是否添加成功(此步可以忽略) #在内核源码文件夹输入 vi .config #输入/HELLO

可以看到如图所示的界面 在这里插入图片描述

第九步,编译内核 make -j5 ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- 第十步,编译完内核后,会在~/build_new/linux/arch/arm64/boot下生成镜像

在这里插入图片描述

第十一步,把sd卡挂载到虚拟机 #先创建2个文件用于挂载sd卡 mkdi ~/data1 mkdir ~/data2 sudo mount /dev/sdb1 ~/data1 sudo mount /dev/sdb2 ~/data2 # 查看内核启动镜像名字 cd ~/data1 vim config.txt # 可以看到kernel = kernel8 #将data1的kernel8.img重命名为kernel8_old.img sudo mv kernel8.img kernel8_old.img #然后将第十步编译的镜像拷贝到data1文件夹,并重命名为kernel8.img sudo cp ~/build_new/linux/arch/arm64/boot/kernel8.img ~/data1/ # 然后退出挂载 sudo umount ~/data1 sudo umount ~/data1 最后将sd卡插入树莓派。 mkdir ~/a.txt dmesg >a.txt grep "hello" a.txt

可以看到驱动成功加载 在这里插入图片描述



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3